package com.suxin.rule.service;

import com.suxin.rule.dto.RuleDTO;
import com.suxin.rule.abstrct.BaseRule;
import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author Tang
 * @classname RuleService
 * @description [  ]
 * @date 2022/1/9 19:19
 */
@Slf4j
public class RuleService {

    private Map<Integer, List<BaseRule>> ruleMap = new HashMap<>();

    private static final int AND = 1;
    private static final int OR = 0;

    public static RuleService create() {
        return new RuleService();
    }

    public RuleService and(List<BaseRule> ruleList) {
        ruleMap.put(AND, ruleList);
        return this;
    }

    public RuleService or(List<BaseRule> ruleList) {
        ruleMap.put(OR, ruleList);
        return this;
    }

    /**
     * execute: 执行器
     * @param dto
     * @return
     */
    public boolean execute(RuleDTO dto) {
        for (Map.Entry<Integer, List<BaseRule>> item : ruleMap.entrySet()) {
            List<BaseRule> ruleList = item.getValue();
            switch (item.getKey()) {
                case AND:
                    return and(dto, ruleList);
                case OR:
                    return or(dto, ruleList);
                default:
                    break;
            }
        }
        return true;
    }

    /**
     * and 关系执行
     * @param dto
     * @param ruleList
     * @return
     */
    private boolean and(RuleDTO dto, List<BaseRule> ruleList) {
        for (BaseRule baseRule : ruleList) {
            boolean execute = baseRule.execute(dto);
            // 匹配所有成功
            if (!execute) {
                return false;
            }
        }
        return true;
    }

    /**
     * or 关系执行
     * @param dto
     * @param ruleList
     * @return
     */
    private boolean or(RuleDTO dto, List<BaseRule> ruleList) {
        for (BaseRule baseRule : ruleList) {
            // 匹配一次成功
            boolean execute = baseRule.execute(dto);
            if (execute) {
                return true;
            }
        }
        return false;
    }

}